package com.demo.sso.sdk.util;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.demo.sso.sdk.model.SsoApiResponse;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.security.cert.X509Certificate;
import java.util.Map;

/**
 * HTTP工具类，用于与SSO服务进行通信
 * 
 * @author SpringCloud团队
 * @version 1.0.0
 * @since 2025-01-01
 */
public class HttpUtils {

    private static final Logger logger = LoggerFactory.getLogger(HttpUtils.class);
    
    private static final ObjectMapper objectMapper = new ObjectMapper();
    
    private final int connectTimeout;
    private final int readTimeout;
    private final boolean ignoreSsl;

    public HttpUtils(int connectTimeout, int readTimeout, boolean ignoreSsl) {
        this.connectTimeout = connectTimeout;
        this.readTimeout = readTimeout;
        this.ignoreSsl = ignoreSsl;
    }

    /**
     * 发送GET请求
     * 
     * @param url 请求URL
     * @return 响应内容
     * @throws IOException IO异常
     */
    public String doGet(String url) throws IOException {
        logger.debug("Sending GET request to: {}", url);
        
        try (CloseableHttpClient httpClient = createHttpClient()) {
            HttpGet httpGet = new HttpGet(url);
            httpGet.setConfig(createRequestConfig());
            httpGet.setHeader("Content-Type", "application/json;charset=UTF-8");
            
            try (CloseableHttpResponse response = httpClient.execute(httpGet)) {
                String responseContent = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
                logger.debug("GET response: {}", responseContent);
                return responseContent;
            }
        }
    }

    /**
     * 发送POST请求
     * 
     * @param url 请求URL
     * @param jsonBody JSON请求体
     * @return 响应内容
     * @throws IOException IO异常
     */
    public String doPost(String url, String jsonBody) throws IOException {
        logger.debug("Sending POST request to: {}, body: {}", url, jsonBody);
        
        try (CloseableHttpClient httpClient = createHttpClient()) {
            HttpPost httpPost = new HttpPost(url);
            httpPost.setConfig(createRequestConfig());
            httpPost.setHeader("Content-Type", "application/json;charset=UTF-8");
            
            if (jsonBody != null && !jsonBody.trim().isEmpty()) {
                StringEntity entity = new StringEntity(jsonBody, StandardCharsets.UTF_8);
                httpPost.setEntity(entity);
            }
            
            try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
                String responseContent = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
                logger.debug("POST response: {}", responseContent);
                return responseContent;
            }
        }
    }

    /**
     * 构建GET请求URL（带参数）
     * 
     * @param baseUrl 基础URL
     * @param params 参数Map
     * @return 完整的URL
     */
    public static String buildGetUrl(String baseUrl, Map<String, String> params) {
        if (params == null || params.isEmpty()) {
            return baseUrl;
        }
        
        StringBuilder url = new StringBuilder(baseUrl);
        if (!baseUrl.contains("?")) {
            url.append("?");
        } else if (!baseUrl.endsWith("&")) {
            url.append("&");
        }
        
        boolean first = true;
        for (Map.Entry<String, String> entry : params.entrySet()) {
            if (!first) {
                url.append("&");
            }
            try {
                url.append(URLEncoder.encode(entry.getKey(), "UTF-8"))
                   .append("=")
                   .append(URLEncoder.encode(entry.getValue(), "UTF-8"));
            } catch (Exception e) {
                logger.warn("Failed to encode parameter: {}={}", entry.getKey(), entry.getValue(), e);
                url.append(entry.getKey()).append("=").append(entry.getValue());
            }
            first = false;
        }
        
        return url.toString();
    }

    /**
     * 解析JSON响应为SsoApiResponse对象
     * 
     * @param jsonResponse JSON响应字符串
     * @param dataClass 数据类型
     * @param <T> 数据类型泛型
     * @return SsoApiResponse对象
     * @throws IOException 解析异常
     */
    public static <T> SsoApiResponse<T> parseResponse(String jsonResponse, Class<T> dataClass) throws IOException {
        try {
            // 先解析为通用的SsoApiResponse
            SsoApiResponse<?> response = objectMapper.readValue(jsonResponse, SsoApiResponse.class);
            
            // 创建结果对象
            SsoApiResponse<T> result = new SsoApiResponse<>(response.getCode(), response.getMsg());
            result.setTimestamp(response.getTimestamp());
            
            // 如果有data且类型匹配，则转换data
            if (response.getData() != null && dataClass != null) {
                T data = objectMapper.convertValue(response.getData(), dataClass);
                result.setData(data);
            }
            
            return result;
        } catch (Exception e) {
            logger.error("Failed to parse JSON response: {}", jsonResponse, e);
            throw new IOException("Failed to parse JSON response", e);
        }
    }

    /**
     * 创建HTTP客户端
     * 
     * @return CloseableHttpClient
     */
    private CloseableHttpClient createHttpClient() {
        if (ignoreSsl) {
            try {
                // 创建信任所有证书的TrustManager
                TrustManager[] trustAllCerts = new TrustManager[]{
                    new X509TrustManager() {
                        @Override
                        public X509Certificate[] getAcceptedIssuers() {
                            return new X509Certificate[0];
                        }

                        @Override
                        public void checkClientTrusted(X509Certificate[] certs, String authType) {
                        }

                        @Override
                        public void checkServerTrusted(X509Certificate[] certs, String authType) {
                        }
                    }
                };

                SSLContext sslContext = SSLContext.getInstance("TLS");
                sslContext.init(null, trustAllCerts, new java.security.SecureRandom());

                return HttpClients.custom()
                        .setSSLContext(sslContext)
                        .setSSLHostnameVerifier((hostname, session) -> true)
                        .build();
            } catch (Exception e) {
                logger.warn("Failed to create SSL-ignore HTTP client, using default client", e);
            }
        }
        
        return HttpClients.createDefault();
    }

    /**
     * 创建请求配置
     * 
     * @return RequestConfig
     */
    private RequestConfig createRequestConfig() {
        return RequestConfig.custom()
                .setConnectTimeout(connectTimeout)
                .setSocketTimeout(readTimeout)
                .setConnectionRequestTimeout(connectTimeout)
                .build();
    }
}